package com.sa.commons.dao.hiber;

import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;

import com.sa.commons.dao.hiber.batchUpdate.GenericBatchUpdateHqlImpl;
import com.sa.commons.dao.hiber.inter.GenericDaoUtil;
import com.sa.commons.dao.hiber.query.GenericQueryHqlImpl;
import com.sa.commons.dao.hiber.util.CreateHqlUtil;
import com.sa.commons.dao.hiber.util.Element;

import com.sa.commons.exception.DBDataErrorException;
import com.sa.commons.exception.DBErrorException;

/**
 * 
 * @author 黄欣
 
 * @param <E>
 * @param <PK>
 */
public class GenericDaoUtilImpl<PK, E> extends GenericQueryHqlImpl<PK, E>
		implements GenericDaoUtil<E> {

	public GenericDaoUtilImpl(Class<? extends E> entityClass) {
		super(entityClass);
	}


	private static final Log log = LogFactory.getLog(GenericDaoUtilImpl.class);

	private String idName = "id";



	public long countAll() throws DBErrorException, DBDataErrorException {
		log.debug("countAll for class=" + entityClass.getName());
		String hql = "select count(*) from " + entityClass.getName();
		try {
			Query query = getSession().createQuery(hql.toString());
			Object object = query.uniqueResult();
			if (null == object) {
				return 0;
			}
			return Long.parseLong(object.toString());
		} catch (RuntimeException re) {
			log.error("countAll for class=" + entityClass.getName()
					+ " failed!", re);
			throw re;
		}
	}

	@SuppressWarnings("unchecked")
	public List<E> findAll() throws DBErrorException, DBDataErrorException {
		log.debug("findAll for class=" + entityClass.getName());
		String hql = "from " + entityClass.getName();
		try {
			Query query = getSession().createQuery(hql.toString());
			return query.list();
		} catch (RuntimeException re) {
			log.error(
					"findAll for class=" + entityClass.getName() + " failed!",
					re);
			throw re;
		}
	}

	public List<E> findAll(int firstResult, int maxResult)
			throws DBErrorException, DBDataErrorException {
		log.debug("findAll for class=" + entityClass.getName());
		return findAll(firstResult, maxResult, new String[] { idName },
				new OrderType[] { OrderType.ASC });
	}

	@SuppressWarnings("unchecked")
	public List<E> findAll(int firstResult, int maxResult,
			String[] orderProperties, OrderType[] types)
			throws DBErrorException, DBDataErrorException {
		log.debug("findAll for class=" + entityClass.getName());
		try {
			StringBuffer queryString = new StringBuffer("from "
					+ entityClass.getName());

			if (orderProperties != null) {
				int length = orderProperties.length;
				int typeLength = types.length;
				if (length != typeLength) {
					throw new DBDataErrorException("排序参数数组的长度必须与排序类型的长度一致！");
				}

				for (int i = 0; i < length; i++) {
					if (i == 0) {
						queryString.append(" order by ");
					}
					queryString.append(orderProperties[i] + " " + types[i]);
					if (i != length - 1) {
						queryString.append(",");
					}
				}
			}

			Query queryObject = getSession()
					.createQuery(queryString.toString());
			queryObject.setFirstResult(firstResult);
			queryObject.setMaxResults(maxResult);
			return queryObject.list();
		} catch (RuntimeException re) {
			log.error(
					"findAll for class=" + entityClass.getName() + " failed!",
					re);
			throw re;
		}
	}

	public void batchUpdate(Map<String, ?> equalsMap,
			Map<String, ? extends Object[]> inMap, Map<String, String> updateMap)
			throws DBErrorException, DBDataErrorException {
		new GenericBatchUpdateHqlImpl<E>(entityClass).batchUpdate(equalsMap,
				inMap, updateMap);
	}

	public void batchUpdate(Map<String, ?> equalsMap,
			Map<String, String> updateMap) throws DBErrorException,
			DBDataErrorException {
		new GenericBatchUpdateHqlImpl<E>(entityClass).batchUpdate(equalsMap,
				updateMap);
	}

	public String getIdName() {
		return idName;
	}

	public void setIdName(String idName) {
		this.idName = idName;
	}

	public Class<? extends E> getEntityClass() {
		return entityClass;
	}

	public void setEntityClass(Class<? extends E> entityClass) {
		this.entityClass = entityClass;
	}

	public List<E> findEntity(List<Element> list)
		throws DBErrorException,DBDataErrorException{
		log.debug("findEntity for class=" + entityClass.getName()+"use element conditions");
		try {
			String hql="from "+entityClass.getName()+CreateHqlUtil.createQueryHql(list);
			Query query=getSession().createQuery(hql);
			return query.list();
		} catch (RuntimeException re) {
			log.error("findEntity for class=" + entityClass.getName()
					+ " failed!", re);
			throw re;
		}
	}

	public List<E> findEntity(List<Element> list, int firstResult, int maxResult) 
		throws DBErrorException,DBDataErrorException{
		log.debug("findEntity for class=" + entityClass.getName()+"use element conditions");
		try {
			String hql="from "+entityClass.getName()+CreateHqlUtil.createQueryHql(list);
			Query query=getSession().createQuery(hql).setFirstResult(firstResult).setMaxResults(maxResult);
			return query.list();
		} catch (RuntimeException re) {
			log.error("findEntity for class=" + entityClass.getName()
					+ " failed!", re);
			throw re;
		}
	}

	public long countEntity(List<Element> list) throws DBErrorException,
			DBDataErrorException {
		return (long)findEntity(list).size();
	}

}
